package se.webbzon.boltzmann.editor.view;

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.AbstractAction;
import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;

import se.webbzon.boltzmann.editor.Main;
import se.webbzon.boltzmann.editor.mvc.EditorModel;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldeditor.WorldAreaBlueprintException;

public class EditorMenuBar extends JMenuBar {
	
	// Auto generated serial version UID
	private static final long serialVersionUID = 2562317057355018803L;
	
	// The world view container associated with this menu bar
	//private final WorldViewContainer worldView;
	
	// The editor mvc-model of this menu bar
	private final EditorModel model;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public EditorMenuBar(WorldViewContainer worldView, EditorModel model) {
		//this.worldView = worldView;
		this.model = model;
	
		JMenu file = new JMenu("File");
		file.add(new JMenuItem(new NewWorldAction()));
		file.add(new JMenuItem(new LoadWorldAction()));
		file.addSeparator();
		file.add(new JMenuItem(new CloseAction()));
		file.addSeparator();
		file.add(new JMenuItem(new SaveWorldAsAction()));
		JMenuItem saveItem = new JMenuItem(new SaveWorldAction());
		saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,KeyEvent.CTRL_MASK));
		file.add(saveItem);
		file.addSeparator();
		file.add(new JMenuItem(new ExitAction()));
		
		JMenu view = new JMenu("View");
		view.add(new JMenuItem(new RefreshAction()));
		
		JMenu world = new JMenu("World");
		JMenuItem gridItem = new JMenuItem(new SetGridAction());
		saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,KeyEvent.CTRL_MASK));
		getActionMap().put("grid", new SetGridAction());
		world.add(gridItem);
		
		add(file);
		add(view);
		add(world);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/*============================================================
	Private Classes
	============================================================*/
	
	/** An implementation of an abstract action used for the New World button. **/
	private final class NewWorldAction extends AbstractAction {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = -4924829900454457915L;
		
		/*============================================================
		Constructors
		============================================================*/

		public NewWorldAction() {
			putValue(AbstractAction.NAME,"New world...");
		}
		
		/*============================================================
		Public Methods
		============================================================*/

		@Override public void actionPerformed(ActionEvent event) {
			model.discardFile(this);
			model.openWorld(this,new WorldArea(WorldArea.RENDERING_ORDER));
		}

	}
	
	/** An implementation of an abstract action used for the Load World button. **/
	private final class LoadWorldAction extends AbstractAction {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = 4553595442671947000L;
		
		/*============================================================
		Constructors
		============================================================*/

		public LoadWorldAction() {
			putValue(AbstractAction.NAME,"Load world...");
		}
		
		/*============================================================
		Public Methods
		============================================================*/

		@Override public void actionPerformed(ActionEvent event) {
			final JFileChooser fileChooser = new JFileChooser();
			int choice = fileChooser.showOpenDialog(EditorMenuBar.this);
			if (choice == JFileChooser.APPROVE_OPTION) try {
				File worldFile = fileChooser.getSelectedFile();
				ArrayList<WorldAreaBlueprintException> nonVitalExceptions =
						new ArrayList<WorldAreaBlueprintException>();
				model.loadWorldFrom(this,worldFile,nonVitalExceptions);
				
				// Show a warning for each non vital exceptions
				for (WorldAreaBlueprintException exception : nonVitalExceptions)
					JOptionPane.showMessageDialog(	EditorMenuBar.this, 
													exception.getMessage(), 
													"Warning", 
													JOptionPane.WARNING_MESSAGE);
			} catch (IOException e) {
				JOptionPane.showMessageDialog(	EditorMenuBar.this, 
												e.getMessage(), 
												"Error", 
												JOptionPane.ERROR_MESSAGE);
			}
		}

	}
	
	/** An implementation of an abstract action used for the Close button. **/
	private final class CloseAction extends AbstractAction {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = 2788732190659896941L;

		/*============================================================
		Constructors
		============================================================*/

		public CloseAction() {
			putValue(AbstractAction.NAME,"Close");
		}
		
		/*============================================================
		Public Methods
		============================================================*/

		@Override public void actionPerformed(ActionEvent event) {
			if (model.hasOpenWorld()) {
				int choice = JOptionPane.showConfirmDialog(	EditorMenuBar.this, 
															"Close current world?", 
															"Confirm", 
															JOptionPane.YES_NO_OPTION, 
															JOptionPane.WARNING_MESSAGE);	
				if (choice == JOptionPane.YES_OPTION)
					model.closeWorld(this);
			}
		}

	}
	
	/** An implementation of an abstract action used for the Save World As button. **/
	private final class SaveWorldAsAction extends AbstractAction {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = -6669662520976334408L;
		
		/*============================================================
		Constructors
		============================================================*/

		public SaveWorldAsAction() {
			putValue(AbstractAction.NAME,"Save world as...");
		}
		
		/*============================================================
		Public Methods
		============================================================*/

		@Override public void actionPerformed(ActionEvent event) {
			final JFileChooser fileChooser = new JFileChooser();
			int choice = fileChooser.showSaveDialog(EditorMenuBar.this);
			if (choice == JFileChooser.APPROVE_OPTION) try {
				File worldFile = fileChooser.getSelectedFile();
				model.saveWorldAs(this,worldFile);
			} catch (WorldAreaBlueprintException | IOException e) {
				JOptionPane.showMessageDialog(	EditorMenuBar.this, 
												e.getMessage(), 
												"Error", 
												JOptionPane.ERROR_MESSAGE);
			}
		}

	}
	
	/** An implementation of an abstract action used for the Save World As button. **/
	private final class SaveWorldAction extends AbstractAction {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = 8521516767962295157L;
		
		/*============================================================
		Constructors
		============================================================*/

		public SaveWorldAction() {
			putValue(AbstractAction.NAME,"Save world");
		}
		
		/*============================================================
		Public Methods
		============================================================*/

		@Override public void actionPerformed(ActionEvent event) {
			try {
				model.saveWorld();
			} catch (WorldAreaBlueprintException | IOException e) {
				JOptionPane.showMessageDialog(	EditorMenuBar.this, 
												e.getMessage(), 
												"Error", 
												JOptionPane.ERROR_MESSAGE);
			}
		}

	}
	
	/** An implementation of an abstract action used for the Exit button. **/
	private final class ExitAction extends AbstractAction {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = 2976325947654800131L;
		
		/*============================================================
		Constructors
		============================================================*/

		public ExitAction() {
			putValue(AbstractAction.NAME,"Exit");
		}
		
		/*============================================================
		Public Methods
		============================================================*/

		@Override public void actionPerformed(ActionEvent event) {
			if (model.hasOpenWorld()) {
				int choice = JOptionPane.showConfirmDialog(	EditorMenuBar.this, 
															"Exit the editor?", 
															"Confirm", 
															JOptionPane.YES_NO_OPTION, 
															JOptionPane.WARNING_MESSAGE);	
				if (choice == JOptionPane.YES_OPTION)
					Main.exit();
			}
		}

	}
	
	/** An implementation of an abstract action used for the Close button. **/
	private final class RefreshAction extends AbstractAction {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = 4367668166339050045L;

		/*============================================================
		Constructors
		============================================================*/

		public RefreshAction() {
			putValue(AbstractAction.NAME,"Refresh");
		}
		
		/*============================================================
		Public Methods
		============================================================*/

		@Override public void actionPerformed(ActionEvent event) {
			JOptionPane.showMessageDialog(EditorMenuBar.this, "Not implemented");
		}

	}
	
	/** An implementation of an abstract action used for the Set Grid button. **/
	private final class SetGridAction extends AbstractAction {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = 4367668166339050045L;

		/*============================================================
		Constructors
		============================================================*/

		public SetGridAction() {
			putValue(AbstractAction.NAME,"Set Grid");
		}
		
		/*============================================================
		Public Methods
		============================================================*/

		@Override public void actionPerformed(ActionEvent event) {
			new GridFrame(model);
		}

	}

}
